package tt.dz.service.imp.base;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tt.dz.dao.ext.common.OmsFactoryListDao;
import tt.dz.dao.ext.system.OmsOperListDao;
import tt.dz.dao.ext.system.OmsOperationBranchSpListDao;
import tt.dz.dao.ext.system.OmsOperationSpListDao;
import tt.dz.dao.ext.system.OmsOperationSpListRepo;
import tt.dz.entity.base.JsonCommon;
import tt.dz.entity.base.JsonForList;
import tt.dz.entity.base.OmsCommonParam;
import tt.dz.entity.base.OmsEntityEnum;
import tt.dz.entity.base.OmsFactoryList;
import tt.dz.entity.exception.BizException;
import tt.dz.entity.exception.OmsDaoException;
import tt.dz.entity.system.OmsOperationSpList;
import tt.dz.entity.system.OmsOperationSpListEntity;
import tt.dz.service.base.OperMerchantService;
import tt.dz.tcp.rpc.ms.SystemMasterServerRpcClient;
import tt.dz.tcp.rpc.ms.client.entity.MasterMerchant;
import tt.dz.tcp.rpc.ms.client.entity.MasterMerchantParam;
import tt.dz.tcp.rpc.ms.client.entity.MasterMerchantResult;
import tt.dz.tcp.rpc.ms.client.entity.MasterQueryMerchantVO;
import tt.dz.util.DateUtils;
import tt.dz.util.StringUtil;
import tt.dz.util.OmsConstant.MsgCodeEnum;

/**
 * @author Administrator
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class OperMerchantServiceImpl extends BaseService implements OperMerchantService
{
	@Autowired
	private OmsFactoryListDao factoryListDao;
	@Autowired
	private OmsOperationSpListDao omsOperationSpListDao;
	@Autowired
	private OmsOperationBranchSpListDao operMerchantBranchDao;
	@Autowired
	private OmsOperListDao operListDao;
	@Autowired
	private SystemMasterServerRpcClient systemMasterServerRpcClient;

	@Autowired
	private OmsOperationSpListRepo omsOperationSpListRepo;

	/*
	 * 因为要生成相关的MaxId，在并发量不大的情况考虑使用
	 * 保证并发访问的时候只有一个id生成
	 * 如果是在集群服务器环境下，也不能保证唯一id生成，分布式下采用乐观方式进行插入。
	 */
	@Override
	public synchronized JsonCommon<OmsOperationSpList> addOmsOperMerchant(OmsOperationSpList oom, String oomType, String factoryId)
	{
		//		//获取相关的Id
		//		if (StringUtils.isEmpty(oomType))
		//		{
		//			return buildOtherJsonCommon(MsgCodeEnum.ERROR400.getMsgCode(), "Error:the request parameter is empty!");
		//		}
		//默认为自营
		oomType = "1";
		//默认非超级运营商
		oom.setSuper_flag(0);
		try
		{
			String currentId = this.genarateIdFormDb(oomType);
			if (currentId == null)
			{
				return this.buildOtherJsonCommon(MsgCodeEnum.ERROR400.getMsgCode(), "genarate id error!!!");
			}
			oom.setOper_merchant_id(currentId);
			//生成一个新的communication_no ，自增
			String new_communication_no = null;
			OmsOperationSpList query = new OmsOperationSpList();
			OmsOperationSpList omsOperMerchant_max = omsOperationSpListDao.findOneExample(query, "(communication_no+0)", "desc");
			if (omsOperMerchant_max != null)
			{
				String no_str = omsOperMerchant_max.getCommunication_no();
				if (StringUtil.isNumeric(no_str))
				{
					String communication_no_original = String.valueOf(Integer.valueOf(no_str) + 1);
					new_communication_no = StringUtil.complement(communication_no_original, 4);
				}
			}
			oom.setCommunication_no(new_communication_no);
			omsOperationSpListDao.add(oom);
			if (StringUtils.isNotEmpty(factoryId))
			{
				OmsFactoryList ofl = new OmsFactoryList();
				ofl.setOper_merchant_id(currentId);
				ofl.setFactory_id(factoryId);
				factoryListDao.updateFactoryList(ofl);
			}
			return this.buildSuccessJsonCommon(oom);
		}
		catch (OmsDaoException e)
		{
			this.logError(e.getMessage(), e);
			return this.buildError400JsonCommon();
		}
	}

	@Override
	public JsonCommon<OmsOperationSpList> updateOmsOperMerchant(OmsOperationSpList oom, String isFactory, String factoryId)
	{
		try
		{
			this.omsOperationSpListDao.update(oom);
			if (StringUtils.isNotEmpty(factoryId))
			{
				OmsFactoryList ofl = new OmsFactoryList();
				ofl.setOper_merchant_id(oom.getOper_merchant_id());
				ofl.setFactory_id(factoryId);
				factoryListDao.updateFactoryList(ofl);
			}
			else
			{
				factoryListDao.updateFactoryByOperId(oom.getOper_merchant_id());
			}
			return this.buildSuccessJsonCommon(oom);
		}
		catch (OmsDaoException e)
		{
			this.logError(e.getMessage(), e);
			return this.buildError400JsonCommon();
		}
	}

	@Override
	public JsonCommon<?> deleteOmsOperMerchant(String id, String delCasecade)
	{
		try
		{
			this.omsOperationSpListDao.deleteById(id, OmsOperationSpList.class);
			//更新厂商信息
			if (StringUtils.isNotEmpty(delCasecade) && "1".equals(delCasecade))
			{
				factoryListDao.updateFactoryByOperId(id);
			}
			//删除下属删除信息
			operMerchantBranchDao.updateBranchByOperId(id);
			//对应运营商信息被删除后，删除用户信息
			this.operListDao.logicDelOperByEntity(OmsEntityEnum.OPERMERCHANT.getValue(), id);
			return this.buildSuccessJsonCommon("success");
		}
		catch (OmsDaoException e)
		{
			this.logError(e.getMessage(), e);
			return this.buildError400JsonCommon();
		}
	}

	@Override
	public JsonForList<OmsOperationSpList> findPageOmsOperMerchant(OmsCommonParam param, OmsOperationSpList oom)
	{
		try
		{
			List<OmsOperationSpList> list = omsOperationSpListDao.pagingFind(param, oom);
			int total = 0;
			if (param.isQueryTotal())
			{
				total = omsOperationSpListDao.queryTotalByObject(new OmsOperationSpList());
			}
			return this.buildSuccessJsonForList(param, list, total);
		}
		catch (Exception e)
		{
			this.logError(e.getMessage(), e);
			return this.buildError400JsonForList();
		}
	}

	@Override
	public void sycnMerchantFromMasterServer() throws BizException
	{
		MasterMerchantParam paramVO = new MasterMerchantParam();
		paramVO.setStartTime("1900-01-01");
		paramVO.setProviderType(0);
		MasterMerchantResult retVO = systemMasterServerRpcClient.systemQueryMerchantInteface(paramVO);
		if (retVO.getIsSuccess() == 1)
		{

			List<MasterMerchant> list_ms = retVO.getResult();

			List<String> valid_ms_list = new ArrayList<>();
			for (MasterMerchant ms : list_ms)
			{
				if (ms.getIsValid() == 1)
					valid_ms_list.add(ms.getMerchantCode());
			}

			List<OmsOperationSpListEntity> all_merchant_list = omsOperationSpListRepo.findAll();

			List<String> valid_merchant_list = new ArrayList<>();
			for (OmsOperationSpListEntity e : all_merchant_list)
			{
				if (e.getValidFlag() != null && e.getValidFlag() == 1)
					valid_merchant_list.add(e.getOperMerchantId());
			}

			List<String> delete_list = new ArrayList<>(valid_merchant_list);
			delete_list.removeAll(valid_ms_list);

			List<String> update_list = new ArrayList<>(valid_merchant_list);
			update_list.retainAll(valid_ms_list);

			List<String> add_list = new ArrayList<>(valid_ms_list);
			add_list.removeAll(valid_merchant_list);

			Date now = new Date();
			Random r = new Random();

			for (OmsOperationSpListEntity e : all_merchant_list)
			{
				if (delete_list.contains(e.getOperMerchantId()))
				{
					e.setValidFlag(0);
					e.setUpdateTime(now);
					e.setUpdateOperId("SyncWithMS");
				}
				else if (update_list.contains(e.getOperMerchantId()))
				{
					MasterMerchant ms = findMasterMerchant(list_ms, e.getOperMerchantId());
					e.setOperName(ms.getName());
					e.setTel(ms.getTelphone());
					e.setUpdateTime(now);
					e.setUpdateOperId("SyncWithMS");
				}
				else if (add_list.contains(e.getOperMerchantId()))
				{
					MasterMerchant ms = findMasterMerchant(list_ms, e.getOperMerchantId());

					e.setValidFlag(1);
					e.setOperName(ms.getName());
					e.setTel(ms.getTelphone());
					e.setUpdateTime(now);
					e.setUpdateOperId("SyncWithMS");

					add_list.remove(e.getOperMerchantId());
				}
			}

			if (!add_list.isEmpty())
			{
				List<OmsOperationSpListEntity> add_entity_list = new ArrayList<>();
				for (String merchantCode : add_list)
				{
					MasterMerchant ms = findMasterMerchant(list_ms, merchantCode);

					OmsOperationSpListEntity entity = new OmsOperationSpListEntity();
					entity.setSuperFlag(0);
					entity.setCreateTime(now);
					entity.setCreateOperId("SyncWithMS");

					int c = r.nextInt(9999);
					entity.setCommunicationNo(String.format("%04d", c));
					entity.setOperMerchantId(ms.getMerchantCode());
					entity.setOperName(ms.getName());
					entity.setTel(ms.getTelphone());
					entity.setValidFlag(1);
					entity.setUpdateTime(now);
					entity.setUpdateOperId("SyncWithMS");
					add_entity_list.add(entity);
				}
				if (!add_entity_list.isEmpty())
					omsOperationSpListRepo.save(add_entity_list);
			}
			omsOperationSpListRepo.save(all_merchant_list);

		}
	}

	private MasterMerchant findMasterMerchant(List<MasterMerchant> list, String merchantCode)
	{
		MasterMerchant m = null;
		for (MasterMerchant ms : list)
		{
			if (ms.getMerchantCode().equals(merchantCode))
			{
				m = ms;
				break;
			}
		}
		return m;
	}

	private String genarateIdFormDb(String oomType) throws OmsDaoException
	{
		String maxId = omsOperationSpListDao.findMaxSequence();
		String lastIdStr = "0";
		if (StringUtils.isNotEmpty(maxId))
		{
			lastIdStr = maxId.replaceFirst("^0*", "");
		}

		if (StringUtils.isNumeric(lastIdStr))
		{
			int idNum = Integer.parseInt(lastIdStr) + 1;
			StringBuilder idSb = new StringBuilder();
			idSb.append(oomType).
					append(DateUtils.formatCurrentDateShort()).
					append(String.format("%03d", idNum));
			return idSb.toString();
		}
		return null;

	}

	@Override
	public String getFactoryId(String oper_merchant_id) {
		OmsFactoryList ofl = new OmsFactoryList();
		ofl.setOper_merchant_id(oper_merchant_id);
		OmsFactoryList oflQQuery = factoryListDao.findOneExample(ofl, null, null);
		if (oflQQuery!=null) {
			return oflQQuery.getFactory_id();
		}
		return null;
	}

}
